#! /usr/bin/python

import httplib, mimetypes
import xml.sax.saxutils as saxutils
import sys
import time

CONN = 0
SSO = ''
header = {
  'Connection':'keep-alive',
  'Host':'www2.balglobal.com',
  'User-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.97 Safari/537.22'
  }

def check_bal_status(username, password):
  localtime   = time.localtime()
  time_str  = time.strftime("%Y/%m/%d %H:%M:%S ", localtime)
  
  # DST check
  timezone    = -(time.altzone if localtime.tm_isdst else time.timezone)
  time_str += "Z" if timezone == 0 else "+" if timezone > 0 else "-"
  time_str += time.strftime("%H%M", time.gmtime(abs(timezone)))
  print('Latest check: ' + time_str)
  print('\r')
  
  login_status = login(username, password)
  if login_status==False:
    return
  get_cookie()
  project_list = get_project_id()
  for project in project_list:
    project_detail_list = get_project_detail(project['ID'])
    print('Project - %s:' % project['ProjectName'])
    for detail in project_detail_list['Detail']:
      print('  %10s - %s' % (detail['Date'], detail['Content']))
    print('\r')
  logout()

def HTML_decode(html):
  ret = saxutils.unescape(html)
  return ret.replace('&nbsp;',' ')

def get_project_detail(project_id):
  global CONN
  global header

  CONN.request('GET','/statuschek/ProjectDetail.aspx?ProjectID=' + str(project_id) + '&ShowHistory=1', None, header)
  response = CONN.getresponse()
  body = str(response.read())

  ret = {}
  ret['ProjectName'] = HTML_decode(get_value(body, 'Project:</td>\r\n                            <td class="greySubHeader"> ', ' \r\n')[0])
  detail_table_list = get_value(body, 'Full Project History</td></tr>', '\r\n                        </table>')
  if len(detail_table_list)==0:
    ret['Detail'] = []
    return ret
  detail_table_str = detail_table_list[0]
  items = get_value(detail_table_str, '">', '<');
  details = []
  for i in range(1, len(items), 3):
    detail_item = {}
    detail_item['Date'] = HTML_decode(items[i])
    detail_item['Content'] = HTML_decode(items[i+1])
    details.append(detail_item)
  ret['Detail'] = details
  return ret

def get_project_id():
  global CONN
  global header

  CONN.request('GET','/statuschek/ProjectList.aspx', None, header)
  response = CONN.getresponse()
  body = str(response.read())
  project_list = get_value(body, 'ProjectDetail.aspx?ProjectID=', '</a>')
  ret = []
  for project_string in project_list:
    project_item = {}
    project_item['ID'] = get_value(project_string, '', '"')[0]
    project_item['ProjectName'] = get_value(project_string, '\r\n', '\r\n')[0].strip()
    ret.append(project_item)
  return ret

def get_cookie():
  global CONN
  global header
  CONN = httplib.HTTPSConnection('www2.balglobal.com')
  CONN.request('GET','/auth/cimssso.aspx?CS=' + SSO, None, header)
  response = CONN.getresponse()
  cookie = get_value(response.getheader('Set-Cookie'), '', ';')[0]
  header['Cookie'] = cookie
  response.read()

def get_value(html, prefix = '', suffix = ''):
  ret = []
  while True:
    if prefix=='':
      p = 0
    else:
      p = html.find(prefix)
      if p==-1:
        return ret
    html = html[p+len(prefix):]
    
    if suffix=='':
      ret.append(html)
      return ret
    else:
      p = html.find(suffix)
      if p==-1:
        return ret
      ret.append(html[:p])
      html = html[p+len(suffix):]

def login(username, password):
  CONN = httplib.HTTPSConnection('cobalt.balglobal.com')
  header = {
    'Connection':'keep-alive',
    'Host':'cobalt.balglobal.com',
    'User-agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.22 (KHTML, like Gecko) Chrome/25.0.1364.97 Safari/537.22'
  }
  CONN.request('GET','/LoginLocal.aspx?u=' + username + '&CP=/StatusChek/', None, header)
  response = CONN.getresponse()
  if response.status == 200:
    response_header = response.getheaders()
    body = str(response.read())
    view_state = get_value(body, 'id="__VIEWSTATE" value="', '" />')[0]
    event_validation = get_value(body, 'id="__EVENTVALIDATION" value="', '" />')[0];
    content_type, post_payload = encode_multipart_formdata({
      '__EVENTTARGET': '',
      '__EVENTARGUMENT': '',
      '__VIEWSTATE': view_state,
      '__EVENTVALIDATION': event_validation,
      'txtUsername': username,
      'txtPassword': password,
      'btnLogin': 'Login'
    })
    post_header = header;
    post_header['Content-Type'] = content_type
    
    CONN.request('POST', '/LoginLocal.aspx?u=' + username + '&CP=/StatusChek/', post_payload, post_header);
    response = CONN.getresponse()
    if response.status == 302:
      response_header = response.getheaders()
      body = str(response.read())
      redirect_location = response.getheader('Location')
      prefix = 'https://www2.balglobal.com/auth/cimssso.aspx?CS='
      
      if not redirect_location.startswith(prefix):
        sys.stderr.write('Login failed. Check username(' + username + ') & password(' + password +') please.\n')
        return False
      global SSO
      SSO = get_value(redirect_location, 'cimssso.aspx?CS=', '')[0]
      return True
      
    else:
      sys.stderr.write('Error while fetching login page: status = ' + str(response.status) + '\n')
      return False
    
  else:
    sys.stderr.write('Error while fetching login page: status = ' + str(response.status) + '\n')
    body = str(response.read())
    sys.stderr.write(body)
    return False

def encode_multipart_formdata(fields, files = {}):
    LIMIT = '----------lImIt_of_THE_fIle_eW_$'
    CRLF = '\r\n'
    L = []
    for (key, value) in fields.items():
        L.append('--' + LIMIT)
        L.append('Content-Disposition: form-data; name="%s"' % key)
        L.append('')
        L.append(value)
    for (key, filename, value) in files:
        L.append('--' + LIMIT)
        L.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
        L.append('Content-Type: %s' % get_content_type(filename))
        L.append('')
        L.append(value)
    L.append('--' + LIMIT + '--')
    L.append('')
    body = CRLF.join(L)
    content_type = 'multipart/form-data; boundary=%s' % LIMIT
    return content_type, body

def get_content_type(filename):
    return mimetypes.guess_type(filename)[0] or 'application/octet-stream'

def logout():
  global CONN
  global header
  header['Connection'] = 'close'
  CONN = httplib.HTTPSConnection('www.balglobal.com')
  CONN.request('GET','/statuschek/login.aspx?logout=true', None, header)
  response = CONN.getresponse()
  response.read()
  CONN.close()

def main():
  if len(sys.argv) != 3:
    sys.stderr.write('Command line H1B status checker for www.balglobal.com (for python 2.x)\n')
    sys.stderr.write('  Usage: python ' + __file__ + ' username password\n')
  else:
    check_bal_status(sys.argv[1], sys.argv[2])

if __name__ == '__main__':
    main()
